package me.ezitku.base.ShapeViews

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.graphics.drawable.StateListDrawable
import android.os.Build
import androidx.annotation.RequiresApi
import android.view.View
import android.widget.TextView

/**
 * Created by yurqi on 2017/8/25.
 */

class ShapeAttribute(var context: Context) {
    var shape: Int = GradientDrawable.RECTANGLE
    val RECTANGLE = 0
    val OVAL = 1
    val LINE = 2
    val RING = 3
    //----------
    var radius = 0f
    var leftTopRadius = 0f
    var rightTopRadius = 0f
    var rightBottomRadius = 0f
    var leftBottomRadius = 0f
    /**
     * 背景颜色
     */
    var color: Int = 0
    /**
     * 字体颜色
     */
    var textColor: Int = 0

    var strokeWidth: Int = 0
    var strokeColor: Int = 0

    var dashWidth: Float = 0F
    var dashGap: Float = 0F
    //----------------------------
    /**
     * 如果设置了这个属性 其他属性不能使用
     */
    var drawable: Drawable? = null
    //Drawable Resource
    /**
     * 如果设置了这个属性 其他属性不能使用
     */
    var drawableRes = 0


    internal fun get(): GradientDrawable {
        if (drawable != null || drawableRes != 0) {
            return GradientDrawable()
        }

        val gd = GradientDrawable()
        gd.useLevel = false

        //Shape | RECTANGLE | OVAL | LINE | RING
        gd.shape = shape
        //Solid Color
        gd.setColor(color)
        // Radius
        if (radius != 0f) {
            gd.cornerRadius = radius
        } else {
            gd.cornerRadii = floatArrayOf(
                    leftTopRadius, leftTopRadius,
                    rightTopRadius, rightTopRadius,
                    rightBottomRadius, rightBottomRadius,
                    leftBottomRadius, leftBottomRadius)
        }
        // Stroke
        if (strokeColor != 0 && strokeWidth != 0){
            gd.setStroke(strokeWidth.toPx.toInt(), strokeColor,dashWidth,dashGap)
        }




        return gd
    }


    private val Int.toPx: Float
        get() {
            val scale = context.resources.displayMetrics.density
            return (this * scale + 0.5f)
        }

    private val Float.toPx
        get() = this.toInt().toPx
}

class Shape(internal var context: Context) {

    internal val drawable = StateListDrawable()
    internal var states = ArrayList<IntArray>()
    internal var textColors = ArrayList<Int>()


    fun focus(action: ShapeAttribute.() -> Unit) {
        var attribute = ShapeAttribute(context)
        action(attribute)
        drawable.set(intArrayOf(android.R.attr.state_enabled,
                android.R.attr.state_focused), attribute)
    }

    fun checked(action: ShapeAttribute.() -> Unit) {
        var attribute = ShapeAttribute(context)
        action(attribute)
        drawable.set(intArrayOf(android.R.attr.state_checked,
                android.R.attr.state_enabled), attribute)
    }

    //States
    fun press(action: ShapeAttribute.() -> Unit) {
        var attribute = ShapeAttribute(context)
        action(attribute)
        drawable.set(intArrayOf(android.R.attr.state_pressed,
                android.R.attr.state_enabled), attribute)
    }


    fun selected(action: ShapeAttribute.() -> Unit) {
        var attribute = ShapeAttribute(context)
        action(attribute)
        drawable.set(intArrayOf(android.R.attr.state_selected,
                android.R.attr.state_enabled), attribute)
    }

    /**
     * 正常状态
     */
    fun normal(action: ShapeAttribute.() -> Unit) {
        var attribute = ShapeAttribute(context)
        action(attribute)
        drawable.set(intArrayOf(android.R.attr.state_enabled), attribute)
        drawable.set(intArrayOf(), attribute)
    }

    internal fun StateListDrawable.set(state: IntArray, attribute: ShapeAttribute) {
        //Set Background Shape
        if (attribute.drawable != null) {
            addState(state, attribute.drawable)
        } else if (attribute.drawableRes != 0) {
            addState(state, context.getDrawable(attribute.drawableRes))
        } else {
            addState(state, attribute.get())
        }
        //Set Text Color Shape
        if (attribute.textColor != 0) {
            states.add(state)
            textColors.add(attribute.textColor)
        } else {
            states.add(state)
            textColors.add(Color.parseColor("#000000"))
        }

    }


}

//fun TextView.Background(action: Shape.() -> Unit) {
//    val shape = Shape(this.context)
//    action(shape)
//    //Set Text Color Shape
//    if (shape.states.size > 0 && shape.textColors.size > 0) {
//        setTextColor(ColorStateList(shape.states.toTypedArray(),
//                shape.textColors.toIntArray()))
//    }
//    //Set Background Shape
//    setBackgroundDrawable(shape.drawable)
//}



fun View.Background(action: Shape.() -> Unit) {
    val shape = Shape(this.context)
    action(shape)
    if(this is TextView){
        if (shape.states.size > 0 && shape.textColors.size > 0) {
            setTextColor(ColorStateList(shape.states.toTypedArray(),
                    shape.textColors.toIntArray()))
        }
    }
    //Set Background Shape
    setBackgroundDrawable(shape.drawable)
}

/**
 * Shape { Selector }
 */
fun View.selector(action: Shape.() -> Unit) {
    val shape = Shape(this.context)
    action(shape)
    if(this is TextView){
        if (shape.states.size > 0 && shape.textColors.size > 0) {
            setTextColor(ColorStateList(shape.states.toTypedArray(),
                    shape.textColors.toIntArray()))
        }
    }
    //Set Background Shape
    setBackgroundDrawable(shape.drawable)
}

private fun addStateDrawable(context: Context, idNormal: Int, idPressed: Int, idFocused: Int): StateListDrawable {

    val sd = StateListDrawable()
    val normal = if (idNormal == -1) null else context.resources.getDrawable(idNormal)
    val pressed = if (idPressed == -1) null else context.resources.getDrawable(idPressed)
    val focus = if (idFocused == -1) null else context.resources.getDrawable(idFocused)

    val sp = GradientDrawable()
    sp.useLevel = false
    sp.shape = GradientDrawable.RECTANGLE
    sp.setColor(Color.RED)
    sp.cornerRadius = 30F

    val sp1 = GradientDrawable()
    sp1.useLevel = false
    sp1.shape = GradientDrawable.RECTANGLE
    sp1.setColor(Color.BLUE)
    sp1.cornerRadius = 30F
    //注意该处的顺序，只要有一个状态与之相配，背景就会被换掉
    //所以不要把大范围放在前面了，如果sd.addState(new[]{},normal)放在第一个的话，就没有什么效果了
//    sd.addState(intArrayOf(android.R.attr.state_enabled, android.R.attr.state_focused), focus)
//    sd.addState(intArrayOf(android.R.attr.state_pressed, android.R.attr.state_enabled), pressed)
//    sd.addState(intArrayOf(android.R.attr.state_focused), focus)
    sd.addState(intArrayOf(android.R.attr.state_pressed), sp)
//    sd.addState(intArrayOf(android.R.attr.state_enabled), sp1)
    sd.addState(intArrayOf(), sp1)
    return sd
}